package com.stylefeng.guns.config.zimg;

import com.stylefeng.guns.config.loadBaseData.ConfigParamContant;
import com.stylefeng.guns.config.redis.RedisUtil;
import com.stylefeng.guns.core.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public class ZimgClient {

//	private String url = "http://192.168.0.201:4869";
	protected Logger LOG = LoggerFactory.getLogger(getClass());

	@Autowired
	private RedisUtil redisUtil;
	
	/**
	 * 上传图片,返回MD5
	 * 
	 * @param bytes       数据
	 * @param contentType 仅支持"jpeg", "jpg", "png", "gif", "webp"
	 * @return
	 */
	public String uploadImg(byte[] bytes, String contentType) {
		Object   url=redisUtil.get(ConfigParamContant.ZIMG_URL);
		RequestConfig config = RequestConfig.custom().setConnectTimeout(5000) // 设置连接超时时间
				.setConnectionRequestTimeout(5000) // 设置请求超时时间
				.setSocketTimeout(5000).setRedirectsEnabled(true)// 默认允许自动重定向
				.build();

		CloseableHttpClient httpClient = HttpClients.createDefault();

		HttpPost httpPost = new HttpPost(url.toString());
		httpPost.setEntity(new ByteArrayEntity(bytes));
		if (contentType != null)
			httpPost.setHeader("Content-type", contentType);
		httpPost.setConfig(config);
		try {
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String returnValue = httpClient.execute(httpPost, responseHandler);
			LOG.debug("{}", returnValue);
			ZimgResult result = JsonUtils.jsonToObject(returnValue, ZimgResult.class);
			if (result.isRet()) {
				return result.getInfo().getMd5();
			} else {
				throw new RuntimeException("image upload fail, " + result.getError().getMessage());
			}
		} catch (ClientProtocolException e) {
			throw new RuntimeException("image upload fail, " + e.getMessage());
		} catch (IOException e) {
			throw new RuntimeException("image upload fail, " + e.getMessage());
		} finally {
			if (httpClient != null) {
				try {
					httpClient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	/**
	 * 删除图片
	 * 
	 * @param id
	 * @return
	 */
	public boolean deleteImg(String id) {
		boolean isSuccess = false;
		Object   url=redisUtil.get(ConfigParamContant.ZIMG_URL);
		if(url==null)
			return  isSuccess;

		RequestConfig config = RequestConfig.custom().setConnectTimeout(5000) // 设置连接超时时间
				.setConnectionRequestTimeout(5000) // 设置请求超时时间
				.setSocketTimeout(5000).setRedirectsEnabled(true)// 默认允许自动重定向
				.build();

		CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpResponse response = null;

		List<NameValuePair> params = new ArrayList<NameValuePair>();
		params.add(new BasicNameValuePair("md5", id));
		params.add(new BasicNameValuePair("t", "1"));

		String queryString = null;
		try {
			queryString = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		HttpGet httpGet = new HttpGet(url + "?" + queryString);
		httpGet.setConfig(config);

		try {
			response = httpClient.execute(httpGet);
			// 检验返回码
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK) {
				isSuccess = true;
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 消耗实体内容
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			// 关闭相应 丢弃http连接
			if (httpClient != null) {
				try {
					httpClient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return isSuccess;
	}

	/********************图片处理*************************/
	/**
	 * 直接给multipartFile加上图片水印再进行保存图片的操作方便省事
	 *
	 * @param multipartFile
	 *            文件上传的对象
	 * @param markImg
	 *            水印文件的路径 如果是相对路径请使用相对路径new Image的方法,此处用的是url
	 * @return
	 * @throws IOException
	 * @author 高永强
	 * @version 2018年11月30日 上午11:15:56
	 */
	public static MultipartFile addPicMarkToMutipartFile(MultipartFile multipartFile,
														 String markImg) throws IOException {
		// 获取图片文件名 xxx.png xxx
		String originFileName = multipartFile.getOriginalFilename();
		// 获取原图片后缀 png
		int lastSplit = originFileName.lastIndexOf(".");
		String suffix = originFileName.substring(lastSplit + 1);
		// 获取图片原始信息
		String dOriginFileName = multipartFile.getOriginalFilename();
		String dContentType = multipartFile.getContentType();
		// 是图片且不是gif才加水印
		if (!suffix.equalsIgnoreCase("gif") && dContentType.contains("image")) {
			// 获取水印图片
			InputStream inputImg = multipartFile.getInputStream();
			Image img = ImageIO.read(inputImg);
			URL url = new URL(markImg);
			// 创建url连接;
			HttpURLConnection urlconn = (HttpURLConnection) url.openConnection();
			urlconn.connect();
			InputStream inputStream = urlconn.getInputStream();
			Image mark = ImageIO.read(inputStream);

			// 加图片水印
			int imgWidth = img.getWidth(null);
			int imgHeight = img.getHeight(null);

			int markWidth = mark.getWidth(null);
			int markHeight = mark.getHeight(null);

			BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight,
					BufferedImage.TYPE_INT_BGR);
			//水印的相对位置  ps：这里是右下角  水印宽为底片的四分之一  位置自己可以调整
			markPic(bufImg, img, mark, imgWidth / 4, (imgWidth * markHeight) / (4 * markWidth),
					imgWidth - imgWidth / 4, imgHeight - (imgWidth * markHeight) / (4 * markWidth));
			ByteArrayOutputStream bs = new ByteArrayOutputStream();
			ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
			ImageIO.write(bufImg, suffix, imOut);
			InputStream is = new ByteArrayInputStream(bs.toByteArray());

			// 加水印后的文件上传
			multipartFile = new MockMultipartFile(dOriginFileName, dOriginFileName, dContentType,
					is);
		}
		//返回加了水印的上传对象
		return multipartFile;
	}

	/**
	 * 加图片水印
	 *
	 * @param bufImg  --BufferedImage  用来画图的宽高跟需要加水印的图片一样的空白图
	 * @param img --需要加水印的图片
	 * @param markImg --水印图片
	 * @param width	--水印图片宽
	 * @param height --水印图片高
	 * @param x	--水印相对于底片的x轴坐标(PS:左上角为(0,0))
	 * @param y  --水印相对于底片的y轴坐标(PS:左上角为(0,0))
	 * @author 高永强
	 * @version 2018年11月30日 上午11:18:51
	 */
	public static void markPic(BufferedImage bufImg, Image img, Image markImg, int width, int height, int x, int y) {
		//取到画笔
		Graphics2D g = bufImg.createGraphics();
		//画底片
		g.drawImage(img, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);
		//画水印位置
		g.drawImage(markImg, x, y, width, height, null);
		g.dispose();
	}

	/**
	 * 加文字水印
	 * @param bufImg --BufferedImage  用来画图的宽高跟需要加水印的图片一样的空白图
	 * @param img --需要加水印的图片
	 * @param text --水印文字
	 * @param font --字体
	 * @param color --颜色
	 * @param x  --水印相对于底片的x轴坐标(PS:左上角为(0,0))
	 * @param y  --水印相对于底片的y轴坐标(PS:左上角为(0,0))
	 * @author 高永强
	 * @version 2018年11月30日 上午11:39:57
	 */
	public static void markWord(BufferedImage bufImg, Image img, String text, Font font, Color color, int x, int y) {
		//取到画笔
		Graphics2D g = bufImg.createGraphics();
		//画底片
		g.drawImage(img, 0, 0, bufImg.getWidth(), bufImg.getHeight(), null);
		g.setColor(color);
		g.setFont(font);
		//位置
		g.drawString(text, x, y);
		g.dispose();
	}

	/**
	 * 直接给multipartFile加上文字水印再进行保存图片的操作方便省事
	 *
	 * @param multipartFile
	 *            文件上传的对象
	 * @param word
	 *            水印文字
	 * @return
	 * @throws IOException
	 * @author 高永强
	 * @version 2018年11月30日 上午11:15:56
	 */
	public static MultipartFile addWorkMarkToMutipartFile(MultipartFile multipartFile,
														  String word) throws IOException {
		// 获取图片文件名 xxx.png xxx
		String originFileName = multipartFile.getOriginalFilename();
		// 获取原图片后缀 png
		int lastSplit = originFileName.lastIndexOf(".");
		String suffix = originFileName.substring(lastSplit + 1);
		// 获取图片原始信息
		String dOriginFileName = multipartFile.getOriginalFilename();
		String dContentType = multipartFile.getContentType();
		// 是图片且不是gif才加水印
		if (!suffix.equalsIgnoreCase("gif") && dContentType.contains("image")) {
			// 获取水印图片
			InputStream inputImg = multipartFile.getInputStream();
			Image img = ImageIO.read(inputImg);
			// 加图片水印
			int imgWidth = img.getWidth(null);
			int imgHeight = img.getHeight(null);

			BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight,
					BufferedImage.TYPE_INT_RGB);
			//设置字体
			Font font = new Font("宋体", Font.ITALIC, 16);
			//调用画文字水印的方法
			markWord(bufImg, img, word, font , Color.BLACK,0 ,14);
			ByteArrayOutputStream bs = new ByteArrayOutputStream();
			ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
			ImageIO.write(bufImg, suffix, imOut);
			InputStream is = new ByteArrayInputStream(bs.toByteArray());

			// 加水印后的文件上传
			multipartFile = new MockMultipartFile(dOriginFileName, dOriginFileName, dContentType,
					is);
		}
		//返回加了水印的上传对象
		return multipartFile;
	}

	/**
	 * 将图片处理为圆形图片
	 * 传入的图片必须是正方形的才会生成圆形 如果是长方形的比例则会变成椭圆的
	 * 
	 * @param url
	 * @return
	 */
	public static BufferedImage transferImgForRoundImgage(String url){
		BufferedImage resultImg = null;
		try {
			if (StringUtils.isBlank(url)) {
				return null;
			}
			BufferedImage buffImg1 = ImageIO.read(new URL(url));
			resultImg = new BufferedImage(buffImg1.getWidth(), buffImg1.getHeight(), BufferedImage.TYPE_INT_RGB);
			Graphics2D g = resultImg.createGraphics();
			Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, buffImg1.getWidth(), buffImg1.getHeight());
			// 使用 setRenderingHint 设置抗锯齿
			g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			resultImg = g.getDeviceConfiguration().createCompatibleImage(buffImg1.getWidth(), buffImg1.getHeight(),
					Transparency.TRANSLUCENT);
			//g.fill(new Rectangle(buffImg2.getWidth(), buffImg2.getHeight()));
			g = resultImg.createGraphics();
			// 使用 setRenderingHint 设置抗锯齿
			g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
			g.setClip(shape);
			g.drawImage(buffImg1, 0, 0, null);
			g.dispose();
		} catch (MalformedURLException e) {
			log.error("URL格式异常" + e.getMessage(), e);
		} catch (IOException e) {
			log.error("读取图片异常" + e.getMessage(), e);
		}
		return resultImg;
	}

	/**
	 * 传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的
	 *
	 * @param url 用户头像地址
	 * @return
	 * @throws IOException
	 */
	public static BufferedImage convertCircular(String url) throws IOException {
		BufferedImage bi1 = ImageIO.read(new URL(url));
		int min=bi1.getHeight()>bi1.getWidth()?bi1.getWidth():bi1.getHeight();
		// 透明底的图片
		BufferedImage bi2 = new BufferedImage(min, min, BufferedImage.TYPE_INT_RGB);
		Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, min, min);
		Graphics2D g2 = bi2.createGraphics();
		g2.setBackground(Color.white);
		g2.fill(new Rectangle(min, min));
		g2.setClip(shape);
		g2.drawImage(bi1, 0, 0, null);
		g2.dispose();
		return bi2;
	}


    /**
     * 传入的图像必须是正方形的 才会 圆形 如果是长方形的比例则会变成椭圆的
     *
     * @param file 用户头像地址
     * @return
     * @throws IOException
     */
    public static BufferedImage cut(MultipartFile  file) throws IOException {
        FileInputStream in = (FileInputStream) file.getInputStream();
        BufferedImage bi1 = ImageIO.read(in);
        int min=bi1.getHeight()>bi1.getWidth()?bi1.getWidth():bi1.getHeight();
        // 根据需要是否使用 BufferedImage.TYPE_INT_ARGB
        BufferedImage image = new BufferedImage(min,min, BufferedImage.TYPE_INT_ARGB);

        Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, min,min);

        Graphics2D g2 = image.createGraphics();
        image = g2.getDeviceConfiguration().createCompatibleImage(min,min,
                Transparency.TRANSLUCENT);
        g2 = image.createGraphics();

        // 将背景设置为透明。如果注释该段代码，默认背景为白色.也可通过g2.setPaint(paint) 设置背景色
        g2.setComposite(AlphaComposite.Clear);
        g2.fill(new Rectangle(min, min));
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.9f));
        g2.setClip(shape);
        // 使用 setRenderingHint 设置抗锯齿
        g2.drawImage(bi1, 0, 0, null);
        g2.dispose();

        try {
            // 输出图地址
            ImageIO.write(image, "PNG", new File("G:\\测试切图\\5.jpg"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;
    }

	/**
	 * 裁剪图片-优化版本；以图片中心为源点，按照长宽比进行图片裁剪，裁剪矩形
	 * @param url
	 * @param widthToHeight 长宽比例，若是为1则是正方形
	 * @return BufferedImage
	 * @throws IOException
	 */
	public static BufferedImage cutPicRect(String url,float widthToHeight) throws IOException{
		BufferedImage bi1 = ImageIO.read(new URL(url));
		int width=bi1.getWidth();
		int height=bi1.getHeight();

		int dw=0;
		int dh=0;
		if(width/(height*1.0)>widthToHeight){//截长
			dw=Math.round(Math.abs(width-widthToHeight*height));
		}else{//截高
			dh=Math.round(Math.abs(height-(1/widthToHeight)*width));
		}

		BufferedImage bi2 = new BufferedImage(width-dw,height-dh,BufferedImage.TYPE_INT_RGB);
		Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, bi1.getWidth(),bi1.getWidth());
		Graphics2D g2 = bi2.createGraphics();
		// 设置颜色
		g2.setBackground(Color.white);
		g2.fill(new Rectangle(bi1.getWidth(), bi1.getWidth()));
		g2.setClip(shape);
		// 使用 setRenderingHint 设置抗锯齿
		g2.drawImage(bi1, -dw/2,-dh/2, null);
		g2.dispose();
		return bi2;
	}
}